
#include "stdafx.h"
#include "ConstDef.h"
#include "Logger.h"
#include "ReloadCode.h"
#include "Interface.h"
#include "IoBuffer.h"
#include "Packet.h"
#include "ReloadPacket.h"
#include "ReloadConfigure.h"

namespace ReloadUdpCall
{
	SignatureAndHashAlgorithm::SignatureAndHashAlgorithm()
		:hash_(HashAlgorithm_None),signature_(SignatureAlgorithm_Anonymous)
	{

	}

	SignatureAndHashAlgorithm::~SignatureAndHashAlgorithm()
	{
		hash_ = HashAlgorithm_None;
		signature_ = SignatureAlgorithm_Anonymous;
	}

	retT SignatureAndHashAlgorithm::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(hash_));
		R(_pBuffer->ntohRead(signature_));
		READFROMBUFFER_END;
	}

	retT SignatureAndHashAlgorithm::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(_pBuffer->htonWrite(hash_));
		R(_pBuffer->htonWrite(signature_));
		WRITETOBUFFER_END;
	}

	std::size_t SignatureAndHashAlgorithm::size()
	{
		return sizeof(hash_) + sizeof(signature_);
	}

	///////////////////////////////////////////////////////////////////////////////////////////////////////////

	GenericCertificate::GenericCertificate()
		:type_(CertificateType_X509)
	{

	}

	GenericCertificate::~GenericCertificate()
	{
		type_ = CertificateType_X509;
	}

	retT GenericCertificate::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(type_));
		R(certificate_.readFromBuffer(_pBuffer));
		READFROMBUFFER_END;
	}

	retT GenericCertificate::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(_pBuffer->htonWrite(type_));
		R(certificate_.writeToBuffer(_pBuffer));
		WRITETOBUFFER_END;
	}

	std::size_t GenericCertificate::size()
	{
		return sizeof(type_) + certificate_.size();
	}

	retT GenericCertificate::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(certificate_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	//////////////////////////////////////////////////////////////////////////////////////////////

	SignerIdentityValue::SignerIdentityValue()
		:hashAlg_(HashAlgorithm_None),pIdentityType_(NULL)
	{

	}

	SignerIdentityValue::~SignerIdentityValue()
	{
		hashAlg_ = HashAlgorithm_None;
		pIdentityType_ = NULL;
	}

	retT SignerIdentityValue::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(hashAlg_));
		if(pIdentityType_)
		{
			switch(*pIdentityType_)
			{
			case SignerIdentityType_CertHash:R(certificateHash_.readFromBuffer(_pBuffer));break;
			case SignerIdentityType_CertHashNodeId:R(certificateNodeIdHash_.readFromBuffer(_pBuffer));break;
			case SignerIdentityType_None:/* empty *//* This structure may be extended with new types if necessary*/break;
			default:RET(INFO_PROTOCOL_RELOAD_SIGNERIDENTITYVALUE_UNKNOWN_TYPE);break;
			}
		}
		else
			RET(ERROR_COMMON_PTR_NULL);
		READFROMBUFFER_END;
	}

	retT SignerIdentityValue::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(_pBuffer->htonWrite(hashAlg_));
		if(pIdentityType_)
		{
			switch(*pIdentityType_)
			{
			case SignerIdentityType_CertHash:R(certificateHash_.writeToBuffer(_pBuffer));break;
			case SignerIdentityType_CertHashNodeId:R(certificateNodeIdHash_.writeToBuffer(_pBuffer));break;
			case SignerIdentityType_None:/* empty *//* This structure may be extended with new types if necessary*/break;
			default:RET(INFO_PROTOCOL_RELOAD_SIGNERIDENTITYVALUE_UNKNOWN_TYPE);break;
			}
		}
		else
			RET(ERROR_COMMON_PTR_NULL);
		WRITETOBUFFER_END;
	}

	std::size_t SignerIdentityValue::size()
	{
		std::size_t totalSize = 0;
		totalSize += sizeof(hashAlg_);
		if(pIdentityType_)
		{
			switch(*pIdentityType_)
			{
			case SignerIdentityType_CertHash:totalSize += certificateHash_.size();break;
			case SignerIdentityType_CertHashNodeId:totalSize += certificateNodeIdHash_.size();break;
			case SignerIdentityType_None:break;
			default:break;
			}
		}
		return totalSize;
	}

	retT SignerIdentityValue::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(certificateHash_.attachRootElement(_pRootElement));
		R(certificateNodeIdHash_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	retT SignerIdentityValue::init( SignerIdentity* _pSignerIdentity, SignerIdentityValue* _pSignerIdentityValue )
	{
		_pSignerIdentityValue->pIdentityType_ = &_pSignerIdentity->identityType_;
		RETSUCCESS;
	}

	//////////////////////////////////////////////////////////////////////////////////////////////////////

	SignerIdentity::SignerIdentity()
		:identityType_(SignerIdentityType_ReservedSignerIdentity),identity_()
	{

	}

	SignerIdentity::SignerIdentity( const SignerIdentity& _signerIdentity )
		:PacketElement(_signerIdentity),identityType_(_signerIdentity.identityType_),identity_()
	{
		for(std::size_t i = 0; i < _signerIdentity.identity_.size(); ++i)
		{
			identity_.push_back(_signerIdentity.identity_[i]);
			identity_[i].pIdentityType_ = &identityType_;
		}
	}

	SignerIdentity::~SignerIdentity()
	{
		identityType_ = SignerIdentityType_ReservedSignerIdentity;
		identity_.clear();
	}

	retT SignerIdentity::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(identityType_));
		uint16	length = 0;
		R(_pBuffer->ntohRead(length));
		R(readContainerFromBuffer(_pBuffer, identity_, length, pRootElement_, (boost::function1< retT, SignerIdentityValue * >)boost::bind(&SignerIdentityValue::init, this, _1)));
		READFROMBUFFER_END;
	}

	retT SignerIdentity::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(_pBuffer->htonWrite(identityType_));
		uint16	length = getTotalSize(identity_.begin(), identity_.end());
		R(_pBuffer->htonWrite(length));
		R(writeContainerToBuffer(_pBuffer, identity_.begin(), identity_.end()));
		WRITETOBUFFER_END;
	}

	std::size_t SignerIdentity::size()
	{
		return sizeof(identityType_) + sizeof(uint16) + getTotalSize(identity_.begin(), identity_.end());
	}

	const SignerIdentity& SignerIdentity::operator=( const SignerIdentity& _signerIdentity )
	{
		PacketElement::operator=(_signerIdentity);
		identityType_ = _signerIdentity.identityType_;
		identity_.clear();
		for(std::size_t i = 0; i < _signerIdentity.identity_.size(); ++i)
		{
			identity_.push_back(_signerIdentity.identity_[i]);
			identity_[i].pIdentityType_ = &identityType_;
		}
		return *this;
	}

	//////////////////////////////////////////////////////////////////////////////////////////////////

	Signature::Signature()
	{

	}

	Signature::~Signature()
	{

	}

	retT Signature::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(algorithm_.readFromBuffer(_pBuffer));
		R(identity_.readFromBuffer(_pBuffer));
		R(signatureValue_.readFromBuffer(_pBuffer));
		READFROMBUFFER_END;
	}

	retT Signature::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(algorithm_.writeToBuffer(_pBuffer));
		R(identity_.writeToBuffer(_pBuffer));
		R(signatureValue_.writeToBuffer(_pBuffer));
		WRITETOBUFFER_END;
	}

	std::size_t Signature::size()
	{
		return algorithm_.size() + identity_.size() + signatureValue_.size();
	}

	retT Signature::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(algorithm_.attachRootElement(_pRootElement));
		R(identity_.attachRootElement(_pRootElement));
		R(signatureValue_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	////////////////////////////////////////////////////////////////////////////////////

	ReloadSecurityBlock::ReloadSecurityBlock()
	{

	}

	ReloadSecurityBlock::~ReloadSecurityBlock()
	{

	}

	retT ReloadSecurityBlock::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(certificates_.readFromBuffer(_pBuffer));
		R(signature_.readFromBuffer(_pBuffer));
		READFROMBUFFER_END;
	}

	retT ReloadSecurityBlock::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(certificates_.writeToBuffer(_pBuffer));
		R(signature_.writeToBuffer(_pBuffer));
		WRITETOBUFFER_END;
	}

	std::size_t ReloadSecurityBlock::size()
	{
		return certificates_.size() + signature_.size();
	}

	retT ReloadSecurityBlock::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(certificates_.attachRootElement(_pRootElement));
		R(signature_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	/////////////////////////////////////////////////////////////////////////////////////

	DataValue::DataValue()
		:exists_(Boolean_True)
	{

	}

	DataValue::DataValue( BooleanT _exists )
		:exists_(_exists)
	{

	}

	DataValue::DataValue( const std::vector<byte>& _array, BooleanT _exists /*= Boolean_True*/ )
		:exists_(_exists)
	{
		R0(setValue(_array));
	}

	DataValue::DataValue( const char* _cstr, BooleanT _exists /*= Boolean_True*/ )
		:exists_(_exists)
	{
		R0(setValue(_cstr));
	}

	DataValue::DataValue( const std::string& _str, BooleanT _exists /*= Boolean_True*/ )
		:exists_(_exists)
	{
		R0(setValue(_str));
	}

	DataValue::~DataValue()
	{
		exists_ = Boolean_False;
	}

	retT DataValue::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(exists_));
		R(value_.readFromBuffer(_pBuffer));
		READFROMBUFFER_END;
	}

	retT DataValue::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(_pBuffer->htonWrite(exists_));
		R(value_.writeToBuffer(_pBuffer));
		WRITETOBUFFER_END;
	}

	std::size_t DataValue::size()
	{
		return sizeof(exists_) + value_.size();
	}

	retT DataValue::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(value_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	retT DataValue::setValue( const std::vector<byte>& _array )
	{
		value_.array_.clear();
		value_.array_.resize(_array.size());
		std::copy(_array.begin(), _array.end(), value_.array_.begin());
		RETSUCCESS;
	}

	retT DataValue::setValue( const char* _cstr )
	{
		value_.array_.clear();
		value_.array_.resize(strlen(_cstr));
		for(std::size_t i = 0; i < value_.array_.size(); ++i)
			value_.array_[i] = (byte)_cstr[i];
		RETSUCCESS;
	}

	retT DataValue::setValue( const std::string& _str )
	{
		value_.array_.clear();
		value_.array_.resize(_str.length());
		for(std::size_t i = 0; i < value_.array_.size(); ++i)
			value_.array_[i] = (byte)_str[i];
		RETSUCCESS;
	}

	std::string DataValue::toString()
	{
		if(value_.array_.size() > 0)
			return std::string((char*)&value_.array_[0], value_.array_.size());
		return std::string();
	}

	/////////////////////////////////////////////////////////////////////////////////////

	ArrayEntry::ArrayEntry()
		:index_(0)
	{

	}

	ArrayEntry::~ArrayEntry()
	{
		index_ = 0;
	}

	retT ArrayEntry::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(index_));
		R(value_.readFromBuffer(_pBuffer));
		READFROMBUFFER_END;
	}

	retT ArrayEntry::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(_pBuffer->htonWrite(index_));
		R(value_.writeToBuffer(_pBuffer));
		WRITETOBUFFER_END;
	}

	std::size_t ArrayEntry::size()
	{
		return sizeof(index_) + value_.size();
	}

	retT ArrayEntry::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(value_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	/////////////////////////////////////////////////////////////////////////////////////

	DictionaryKey::DictionaryKey()
	{

	}

	DictionaryKey::DictionaryKey( const std::vector<byte>& _array )
	{
		R0(setValue(_array));
	}

	DictionaryKey::DictionaryKey( const char* _cstr )
	{
		R0(setValue(_cstr));
	}

	DictionaryKey::DictionaryKey( const std::string& _str )
	{
		R0(setValue(_str));
	}

	DictionaryKey::~DictionaryKey()
	{

	}

	retT DictionaryKey::setValue( const std::vector<byte>& _array )
	{
		array_.clear();
		array_.resize(_array.size());
		std::copy(_array.begin(), _array.end(), array_.begin());
		RETSUCCESS;
	}

	retT DictionaryKey::setValue( const char* _cstr )
	{
		array_.clear();
		array_.resize(strlen(_cstr));
		for(std::size_t i = 0; i < array_.size(); ++i)
			array_[i] = (byte)_cstr[i];
		RETSUCCESS;
	}

	retT DictionaryKey::setValue( const std::string& _str )
	{
		array_.clear();
		array_.resize(_str.length());
		for(std::size_t i = 0; i < array_.size(); ++i)
			array_[i] = (byte)_str[i];
		RETSUCCESS;
	}

	std::string DictionaryKey::toString()
	{
		if(array_.size() > 0)
			return std::string((char*)&array_[0], array_.size());
		return std::string();
	}

	/////////////////////////////////////////////////////////////////////////////////////

	DictionaryEntry::DictionaryEntry()
	{

	}

	DictionaryEntry::~DictionaryEntry()
	{

	}

	retT DictionaryEntry::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(key_.readFromBuffer(_pBuffer));
		R(value_.readFromBuffer(_pBuffer));
		READFROMBUFFER_END;
	}

	retT DictionaryEntry::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(key_.writeToBuffer(_pBuffer));
		R(value_.writeToBuffer(_pBuffer));
		WRITETOBUFFER_END;
	}

	std::size_t DictionaryEntry::size()
	{
		return key_.size() + value_.size();
	}

	retT DictionaryEntry::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(key_.attachRootElement(_pRootElement));
		R(value_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	/////////////////////////////////////////////////////////////////////////////////////

	StoredDataValue::StoredDataValue()
		:pStoredData_(NULL)
	{

	}

	StoredDataValue::~StoredDataValue()
	{
		pStoredData_ = NULL;
	}

	retT StoredDataValue::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		if(pStoredData_ && pStoredData_->pKindData_ && pStoredData_->pKindData_->pKindBlock_)
		{
			switch(pStoredData_->pKindData_->pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:R(singleValueEntry_.readFromBuffer(_pBuffer));break;
			case DataModel_Array:R(arrayEntry_.readFromBuffer(_pBuffer));break;
			case DataModel_Dictionary:R(dictionaryEntry_.readFromBuffer(_pBuffer));break;
			default:break;
			}
		}
		else
			RET(ERROR_COMMON_PTR_NULL);
		READFROMBUFFER_END;
	}

	retT StoredDataValue::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		if(pStoredData_ && pStoredData_->pKindData_ && pStoredData_->pKindData_->pKindBlock_)
		{
			switch(pStoredData_->pKindData_->pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:R(singleValueEntry_.writeToBuffer(_pBuffer));break;
			case DataModel_Array:R(arrayEntry_.writeToBuffer(_pBuffer));break;
			case DataModel_Dictionary:R(dictionaryEntry_.writeToBuffer(_pBuffer));break;
			default:break;
			}
		}
		else
			RET(ERROR_COMMON_PTR_NULL);
		WRITETOBUFFER_END;
	}

	std::size_t StoredDataValue::size()
	{
		std::size_t totalSize_ = 0;
		if(pStoredData_ && pStoredData_->pKindData_ && pStoredData_->pKindData_->pKindBlock_)
		{
			switch(pStoredData_->pKindData_->pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:totalSize_ += singleValueEntry_.size();break;
			case DataModel_Array:totalSize_ += arrayEntry_.size();break;
			case DataModel_Dictionary:totalSize_ += dictionaryEntry_.size();break;
			default:break;
			}
		}
		return totalSize_;
	}

	retT StoredDataValue::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(singleValueEntry_.attachRootElement(_pRootElement));
		R(arrayEntry_.attachRootElement(_pRootElement));
		R(dictionaryEntry_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	/////////////////////////////////////////////////////////////////////////////////////

	StoredData::StoredData()
		:length_(0),storageTime_(0),lifetime_(DEFAULT_STOREDDATA_LIFETIME),pKindData_(NULL)
	{

	}

	StoredData::StoredData( const StoredData& _storedData )
		:PacketElement(_storedData),length_(_storedData.length_),storageTime_(_storedData.storageTime_),lifetime_(_storedData.lifetime_),value_(_storedData.value_),pKindData_(_storedData.pKindData_)
	{
		value_.pStoredData_ = this;
	}

	StoredData::~StoredData()
	{
		length_ = 0;
		storageTime_ = 0;
		lifetime_ = 0;
		pKindData_ = NULL;
	}

	retT StoredData::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(length_));
		if(pKindData_ && pKindData_->pKindBlock_)
		{
			R(_pBuffer->ntohRead(storageTime_));
			R(_pBuffer->ntohRead(lifetime_));
			R(value_.readFromBuffer(_pBuffer));
		}
		else
			R(_pBuffer->consume(length_));
		READFROMBUFFER_END;
	}

	retT StoredData::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		length_ = size() - sizeof(length_);
		R(_pBuffer->htonWrite(length_));
		R(_pBuffer->htonWrite(storageTime_));
		R(_pBuffer->htonWrite(lifetime_));
		R(value_.writeToBuffer(_pBuffer));
		WRITETOBUFFER_END;
	}

	std::size_t StoredData::size()
	{
		std::size_t totalSize = 0;
		totalSize += sizeof(length_);
		if(pKindData_ && pKindData_->pKindBlock_)
		{
			totalSize += sizeof(storageTime_) + sizeof(lifetime_) + value_.size();
		}
		else
			totalSize += length_;
		return totalSize;
	}

	retT StoredData::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(value_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	retT StoredData::init( KindData* _pKindData, StoredData* _pStoredData )
	{
		_pStoredData->pKindData_ = _pKindData;
		_pStoredData->value_.pStoredData_ = _pStoredData;
		RETSUCCESS;
	}

	const StoredData& StoredData::operator=( const StoredData& _storedData )
	{
		PacketElement::operator=(_storedData);
		length_ = _storedData.length_;
		storageTime_ = _storedData.storageTime_;
		lifetime_ = _storedData.lifetime_;
		value_ = _storedData.value_;
		pKindData_ = _storedData.pKindData_;
		value_.pStoredData_ = this;
		return *this;
	}

	/////////////////////////////////////////////////////////////////////////////////////

	StoredDataPtr::StoredDataPtr()
		:pDataValue_(NULL)
	{

	}

	StoredDataPtr::~StoredDataPtr()
	{
		pDataValue_ = NULL;
	}

	/////////////////////////////////////////////////////////////////////////////////////

	KindData::KindData()
		:kind_(0),generationCounter_(0),pKindBlock_(NULL),array_(),dictionary_()
	{

	}

	KindData::KindData( const KindData& _kindData )
		:PacketElement(_kindData),kind_(_kindData.kind_),generationCounter_(_kindData.generationCounter_),pKindBlock_(_kindData.pKindBlock_)
	{
		array_.clear();
		dictionary_.clear();
		for(std::list<StoredData>::const_iterator it = _kindData.values_.list_.begin(); it != _kindData.values_.list_.end(); ++it)
		{
			switch(pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:
				{
					if(it != _kindData.values_.list_.begin())
						R0(INFO_PROTOCOL_RELOAD_TOO_MANY_ELEMENTS_FOR_DATAMODEL_SINGLE);
					R0(setSingleValueEntry(*it));
					break;
				}
			case DataModel_Array:R0(setArrayEntry(*it));break;
			case DataModel_Dictionary:R0(setDictionaryEntry(*it));break;
			default:R0(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
			}
		}
	}

	KindData::~KindData()
	{
		kind_ = 0;
		generationCounter_ = 0;
		pKindBlock_ = NULL;
		array_.clear();
		dictionary_.clear();
	}

	retT KindData::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(kind_));
		R(init(kind_));
		R(_pBuffer->ntohRead(generationCounter_));
		StructVarList<uint32, StoredData> values;
		R(values.attachRootElement(pRootElement_));
		R(values.readFromBuffer(_pBuffer, (boost::function1< retT, StoredData * >)boost::bind(&StoredData::init, this, _1)));
		if(pKindBlock_ != NULL)
		{
			for(std::list<StoredData>::iterator it = values.list_.begin(); it != values.list_.end(); ++it)
			{
				switch(pKindBlock_->kind_.dataModel_)
				{
				case DataModel_Single:
					{
						if(it != values.list_.begin())
							RET(INFO_PROTOCOL_RELOAD_TOO_MANY_ELEMENTS_FOR_DATAMODEL_SINGLE);
						R(setSingleValueEntry(*it));
						break;
					}
				case DataModel_Array:R(setArrayEntry(*it));break;
				case DataModel_Dictionary:R(setDictionaryEntry(*it));break;
				default:break;
				}
			}
		}
		READFROMBUFFER_END;
	}

	retT KindData::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(init(kind_));
		R(_pBuffer->htonWrite(kind_));
		R(_pBuffer->htonWrite(generationCounter_));
		R(values_.writeToBuffer(_pBuffer));
		WRITETOBUFFER_END;
	}

	std::size_t KindData::size()
	{
		RU(init(kind_), 0);
		return sizeof(kind_) + sizeof(generationCounter_) + values_.size();
	}

	retT KindData::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(values_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	int KindData::init( KindId _kind )
	{
		boost::unordered_map<KindId, KindBlock>::const_iterator it = overlayConfiguration_.requiredKinds_.find(_kind);
		if(it != overlayConfiguration_.requiredKinds_.end())
		{
			pKindBlock_ = &it->second;
			kind_ = _kind;
		}
		else
			pKindBlock_ = NULL;
		RETSUCCESS;
	}

	const KindData& KindData::operator=( const KindData& _kindData )
	{
		PacketElement::operator=(_kindData);
		kind_ = _kindData.kind_;
		generationCounter_ = _kindData.generationCounter_;
		pKindBlock_ = _kindData.pKindBlock_;
		array_.clear();
		dictionary_.clear();
		for(std::list<StoredData>::const_iterator it = _kindData.values_.list_.begin(); it != _kindData.values_.list_.end(); ++it)
		{
			switch(pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:
				{
					if(it != _kindData.values_.list_.begin())
						RU(INFO_PROTOCOL_RELOAD_TOO_MANY_ELEMENTS_FOR_DATAMODEL_SINGLE, *this);
					RU(setSingleValueEntry(*it), *this);
					break;
				}
			case DataModel_Array:RU(setArrayEntry(*it), *this);break;
			case DataModel_Dictionary:RU(setDictionaryEntry(*it), *this);break;
			default:RU(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE, *this);
			}
		}
		return *this;
	}

	retT KindData::setSingleValueEntry( const StoredData& _singleValueEntry )
	{
		if(pKindBlock_->kind_.dataModel_ != DataModel_Single)
			RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
		if(values_.list_.begin() == values_.list_.end())
			values_.list_.push_back(_singleValueEntry);
		else
			*values_.list_.begin() = _singleValueEntry;
		R(StoredData::init(this, &(*values_.list_.begin())));
		RETSUCCESS;
	}

	retT KindData::setSingleValueEntry( const DataValue& _singleDataValue )
	{
		StoredData storedData;
		storedData.value_.singleValueEntry_ = _singleDataValue;
		R(setSingleValueEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setSingleValueEntry( const NumericVarArray<uint32, byte>& _value )
	{
		StoredData storedData;
		storedData.value_.singleValueEntry_.exists_ = Boolean_True;
		storedData.value_.singleValueEntry_.value_ = _value;
		R(setSingleValueEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setSingleValueEntry( const std::vector<byte>& _array )
	{
		StoredData storedData;
		storedData.value_.singleValueEntry_.exists_ = Boolean_True;
		storedData.value_.singleValueEntry_.value_ = _array;
		R(setSingleValueEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setSingleValueEntry( const char* _cstr )
	{
		StoredData storedData;
		storedData.value_.singleValueEntry_.value_.array_.clear();
		storedData.value_.singleValueEntry_.value_.array_.resize(strlen(_cstr));
		for(std::size_t i = 0; i < storedData.value_.singleValueEntry_.value_.array_.size(); ++i)
			storedData.value_.singleValueEntry_.value_.array_[i] = (byte)_cstr[i];
		R(setSingleValueEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setSingleValueEntry( const std::string& _str )
	{
		R(setSingleValueEntry(_str.c_str()));
		RETSUCCESS;
	}

	retT KindData::getSingleValueEntry( StoredDataPtr& _storedDataPtrOut )
	{
		if(pKindBlock_->kind_.dataModel_ != DataModel_Single)
			RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
		if(values_.list_.begin() == values_.list_.end())
		{
			_storedDataPtrOut.pStoredData_ = values_.list_.end();
			_storedDataPtrOut.pDataValue_ = NULL;
		}
		else
		{
			_storedDataPtrOut.pStoredData_ = values_.list_.begin();
			_storedDataPtrOut.pDataValue_ = &values_.list_.begin()->value_.singleValueEntry_;
		}
		RETSUCCESS;
	}

	retT KindData::deleteSingleValueEntry()
	{
		if(pKindBlock_->kind_.dataModel_ != DataModel_Single)
			RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
		values_.list_.erase(values_.list_.begin());
		RETSUCCESS;
	}

	retT KindData::setArrayEntry( const StoredData& _arrayEntry )
	{
		if(pKindBlock_->kind_.dataModel_ != DataModel_Array)
			RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
		uint32 arrayEntryIndex = _arrayEntry.value_.arrayEntry_.index_;
		if(arrayEntryIndex == ARRAY_ENTRY_INDEX_END)
		{
			uint32 indexEnd = array_.size();
			while(indexEnd > 0 && (array_[indexEnd - 1].pDataValue_ == NULL || array_[indexEnd - 1].pDataValue_->exists_ == Boolean_False))
				--indexEnd;
			arrayEntryIndex = indexEnd;
		}
		if(array_.size() < arrayEntryIndex + 1)
			array_.resize(arrayEntryIndex + 1);
		if(array_[arrayEntryIndex].pDataValue_ == NULL)
		{
			values_.list_.push_back(_arrayEntry);
			array_[arrayEntryIndex].pStoredData_ = --values_.list_.end();
			array_[arrayEntryIndex].pDataValue_ = &array_[arrayEntryIndex].pStoredData_->value_.arrayEntry_.value_;
		}
		else
		{
			*array_[arrayEntryIndex].pStoredData_ = _arrayEntry;
			array_[arrayEntryIndex].pDataValue_ = &array_[arrayEntryIndex].pStoredData_->value_.arrayEntry_.value_;
		}
		R(StoredData::init(this, &(*array_[arrayEntryIndex].pStoredData_)));
		RETSUCCESS;
	}

	retT KindData::setArrayEntry( uint32 _index, const DataValue& _arrayDataValue )
	{
		StoredData storedData;
		storedData.value_.arrayEntry_.index_ = _index;
		storedData.value_.arrayEntry_.value_ = _arrayDataValue;
		R(setArrayEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setArrayEntry( uint32 _index, const NumericVarArray<uint32, byte>& _value )
	{
		StoredData storedData;
		storedData.value_.arrayEntry_.index_ = _index;
		storedData.value_.arrayEntry_.value_.exists_ = Boolean_True;
		storedData.value_.arrayEntry_.value_.value_ = _value;
		R(setArrayEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setArrayEntry( uint32 _index, const std::vector<byte>& _array )
	{
		StoredData storedData;
		storedData.value_.arrayEntry_.index_ = _index;
		storedData.value_.arrayEntry_.value_.exists_ = Boolean_True;
		storedData.value_.arrayEntry_.value_.value_ = _array;
		R(setArrayEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setArrayEntry( uint32 _index, const char* _cstr )
	{
		StoredData storedData;
		storedData.value_.arrayEntry_.index_ = _index;
		storedData.value_.arrayEntry_.value_.value_.array_.clear();
		storedData.value_.arrayEntry_.value_.value_.array_.resize(strlen(_cstr));
		for(std::size_t i = 0; i < storedData.value_.arrayEntry_.value_.value_.array_.size(); ++i)
			storedData.value_.arrayEntry_.value_.value_.array_[i] = (byte)_cstr[i];
		R(setArrayEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setArrayEntry( uint32 _index, const std::string& _str )
	{
		R(setArrayEntry(_index, _str.c_str()));
		RETSUCCESS;
	}

	retT KindData::getArrayEntry( uint32 _index, StoredDataPtr& _storedDataPtrOut )
	{
		if(pKindBlock_->kind_.dataModel_ != DataModel_Array)
			RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
		if(array_.size() < _index + 1)
		{
			_storedDataPtrOut.pStoredData_ = values_.list_.end();
			_storedDataPtrOut.pDataValue_ = NULL;
		}
		else
		{
			_storedDataPtrOut.pStoredData_ = array_[_index].pStoredData_;
			_storedDataPtrOut.pDataValue_ = array_[_index].pDataValue_;
		}
		RETSUCCESS;
	}

	retT KindData::deleteArrayEntry( uint32 _index )
	{
		if(pKindBlock_->kind_.dataModel_ != DataModel_Array)
			RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
		if(array_.size() < _index + 1)
			RETSUCCESS;
		if(array_[_index].pDataValue_ == NULL)
			RETSUCCESS;
		values_.list_.erase(array_[_index].pStoredData_);
		array_[_index].pStoredData_ = values_.list_.end();
		array_[_index].pDataValue_ = NULL;
		RETSUCCESS;
	}

	retT KindData::setDictionaryEntry( const StoredData& _dictionaryEntry )
	{
		if(pKindBlock_->kind_.dataModel_ != DataModel_Dictionary)
			RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
		if(dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pDataValue_ == NULL)
		{
			values_.list_.push_back(_dictionaryEntry);
			dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_ = --values_.list_.end();
			dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pDataValue_ = &dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_->value_.dictionaryEntry_.value_;
		}
		else
		{
			*dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_ = _dictionaryEntry;
			dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pDataValue_ = &dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_->value_.dictionaryEntry_.value_;
		}
		R(StoredData::init(this, &(*dictionary_[_dictionaryEntry.value_.dictionaryEntry_.key_].pStoredData_)));
		RETSUCCESS;
	}

	retT KindData::setDictionaryEntry( const DictionaryKey& _key, const DataValue& _dictionaryDataValue )
	{
		StoredData storedData;
		storedData.value_.dictionaryEntry_.key_ = _key;
		storedData.value_.dictionaryEntry_.value_ = _dictionaryDataValue;
		R(setDictionaryEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setDictionaryEntry( const DictionaryKey& _key, const NumericVarArray<uint32, byte>& _value )
	{
		StoredData storedData;
		storedData.value_.dictionaryEntry_.key_ = _key;
		storedData.value_.dictionaryEntry_.value_.exists_ = Boolean_True;
		storedData.value_.dictionaryEntry_.value_.value_ = _value;
		R(setDictionaryEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setDictionaryEntry( const DictionaryKey& _key, const std::vector<byte>& _array )
	{
		StoredData storedData;
		storedData.value_.dictionaryEntry_.key_ = _key;
		storedData.value_.dictionaryEntry_.value_.exists_ = Boolean_True;
		storedData.value_.dictionaryEntry_.value_.value_ = _array;
		R(setDictionaryEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setDictionaryEntry( const DictionaryKey& _key, const char* _cstr )
	{
		StoredData storedData;
		storedData.value_.dictionaryEntry_.key_ = _key;
		storedData.value_.dictionaryEntry_.value_.value_.array_.clear();
		storedData.value_.dictionaryEntry_.value_.value_.array_.resize(strlen(_cstr));
		for(std::size_t i = 0; i < storedData.value_.dictionaryEntry_.value_.value_.array_.size(); ++i)
			storedData.value_.dictionaryEntry_.value_.value_.array_[i] = (byte)_cstr[i];
		R(setDictionaryEntry(storedData));
		RETSUCCESS;
	}

	retT KindData::setDictionaryEntry( const DictionaryKey& _key, const std::string& _str )
	{
		R(setDictionaryEntry(_key, _str.c_str()));
		RETSUCCESS;
	}

	retT KindData::getDictionaryEntry( const DictionaryKey& _key, StoredDataPtr& _storedDataPtrOut )
	{
		if(pKindBlock_->kind_.dataModel_ != DataModel_Dictionary)
			RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
		if(dictionary_.find(_key) == dictionary_.end())
		{
			_storedDataPtrOut.pStoredData_ = values_.list_.end();
			_storedDataPtrOut.pDataValue_ = NULL;
		}
		else
		{
			_storedDataPtrOut.pStoredData_ = dictionary_[_key].pStoredData_;
			_storedDataPtrOut.pDataValue_ = dictionary_[_key].pDataValue_;
		}
		RETSUCCESS;
	}

	retT KindData::deleteDictionaryEntry( const DictionaryKey& _key )
	{
		if(pKindBlock_->kind_.dataModel_ != DataModel_Dictionary)
			RET(INFO_PROTOCOL_RELOAD_WRONG_DATAMODEL);
		if(dictionary_.find(_key) == dictionary_.end())
			RETSUCCESS;
		if(dictionary_[_key].pDataValue_ == NULL)
		{
			dictionary_.erase(_key);
			RETSUCCESS;
		}
		values_.list_.erase(dictionary_[_key].pStoredData_);
		dictionary_.erase(_key);
		RETSUCCESS;
	}

	retT KindData::setEntry( const StoredData& _entry )
	{
		if(_entry.pKindData_ && _entry.pKindData_->pKindBlock_)
		{
			switch(_entry.pKindData_->pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:R(setSingleValueEntry(_entry));break;
			case DataModel_Array:R(setArrayEntry(_entry));break;
			case DataModel_Dictionary:R(setDictionaryEntry(_entry));break;
			default:RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
			}
		}
		else
		{
			RET(ERROR_COMMON_PTR_NULL);
		}
		RETSUCCESS;
	}

	retT KindData::getEntry( const StoredData& _entry, StoredDataPtr& _storedDataPtrOut )
	{
		if(_entry.pKindData_ && _entry.pKindData_->pKindBlock_)
		{
			switch(_entry.pKindData_->pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:R(getSingleValueEntry(_storedDataPtrOut));break;
			case DataModel_Array:R(getArrayEntry(_entry.value_.arrayEntry_.index_, _storedDataPtrOut));break;
			case DataModel_Dictionary:R(getDictionaryEntry(_entry.value_.dictionaryEntry_.key_, _storedDataPtrOut));break;
			default:RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
			}
		}
		else
		{
			RET(ERROR_COMMON_PTR_NULL);
		}
		RETSUCCESS;
	}

	retT KindData::deleteEntry( const StoredData& _entry )
	{
		if(_entry.pKindData_ && _entry.pKindData_->pKindBlock_)
		{
			switch(_entry.pKindData_->pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:R(deleteSingleValueEntry());break;
			case DataModel_Array:R(deleteArrayEntry(_entry.value_.arrayEntry_.index_));break;
			case DataModel_Dictionary:R(deleteDictionaryEntry(_entry.value_.dictionaryEntry_.key_));break;
			default:RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
			}
		}
		else
		{
			RET(ERROR_COMMON_PTR_NULL);
		}
		RETSUCCESS;
	}

	////////////////////////////////////////////////////////////////////////////////////

	StoreKindData::StoreKindData()
	{

	}

	StoreKindData::~StoreKindData()
	{

	}

	///////////////////////////////////////////////////////////////////////////////////

	ArrayRange::ArrayRange()
		:first_(0),last_(0)
	{

	}

	ArrayRange::~ArrayRange()
	{
		first_ = 0;
		last_ = 0;
	}

	retT ArrayRange::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(first_));
		R(_pBuffer->ntohRead(last_));
		READFROMBUFFER_END;
	}

	retT ArrayRange::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		R(_pBuffer->htonWrite(first_));
		R(_pBuffer->htonWrite(last_));
		WRITETOBUFFER_END;
	}

	std::size_t ArrayRange::size()
	{
		return sizeof(first_) + sizeof(last_);
	}

	bool operator<( const ArrayRange& _arrayRangeLeft, const ArrayRange& _arrayRangeRight )
	{
		return _arrayRangeLeft.first_ < _arrayRangeRight.first_;
	}

	/////////////////////////////////////////////////////////////////////////////////////

	StoredDataSpecifier::StoredDataSpecifier()
		:kind_(0),generation_(0),length_(0),pKindBlock_(NULL)
	{

	}

	StoredDataSpecifier::~StoredDataSpecifier()
	{
		kind_ = 0;
		generation_ = 0;
		length_ = 0;
		pKindBlock_ = NULL;
	}

	int StoredDataSpecifier::init( KindId _kind )
	{
		boost::unordered_map<KindId, KindBlock>::const_iterator it = overlayConfiguration_.requiredKinds_.find(_kind);
		if(it != overlayConfiguration_.requiredKinds_.end())
		{
			pKindBlock_ = &it->second;
			kind_ = _kind;
		}
		else
			pKindBlock_ = NULL;
		RETSUCCESS;
	}

	retT StoredDataSpecifier::readFromBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		READFROMBUFFER_START;
		R(_pBuffer->ntohRead(kind_));
		R(init(kind_));
		R(_pBuffer->ntohRead(generation_));
		R(_pBuffer->ntohRead(length_));
		if(pKindBlock_ != NULL)
		{
			switch(pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:break;
			case DataModel_Array:R(modelSpecifier_.indices_.readFromBuffer(_pBuffer));break;
			case DataModel_Dictionary:R(modelSpecifier_.keys_.readFromBuffer(_pBuffer));break;
			default:R(_pBuffer->consume(length_));RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
			}
		}
		else
			R(_pBuffer->consume(length_));
		READFROMBUFFER_END;
	}

	retT StoredDataSpecifier::writeToBuffer( boost::shared_ptr<IoBuffer> _pBuffer )
	{
		WRITETOBUFFER_START;
		boost::unordered_map<KindId, KindBlock>::const_iterator it = overlayConfiguration_.requiredKinds_.find(kind_);
		if(it != overlayConfiguration_.requiredKinds_.end())
		{
			pKindBlock_ = &it->second;
		}
		else
			RET(INFO_PROTOCOL_RELOAD_UNKNOWN_KIND);
		R(_pBuffer->htonWrite(kind_));
		R(_pBuffer->htonWrite(generation_));
		length_ = size() - sizeof(kind_) - sizeof(generation_) - sizeof(length_);
		R(_pBuffer->htonWrite(length_));
		switch(pKindBlock_->kind_.dataModel_)
		{
		case DataModel_Single:break;
		case DataModel_Array:R(modelSpecifier_.indices_.writeToBuffer(_pBuffer));break;
		case DataModel_Dictionary:R(modelSpecifier_.keys_.writeToBuffer(_pBuffer));break;
		default:R(_pBuffer->produce(length_));RET(INFO_PROTOCOL_RELOAD_UNKNOWN_DATAMODEL_TYPE);
		}
		WRITETOBUFFER_END;
	}

	std::size_t StoredDataSpecifier::size()
	{
		RU(init(kind_), 0);
		std::size_t totalSize = 0;
		totalSize += sizeof(kind_);
		totalSize += sizeof(generation_);
		totalSize += sizeof(length_);
		if(pKindBlock_ != NULL)
		{
			switch(pKindBlock_->kind_.dataModel_)
			{
			case DataModel_Single:break;
			case DataModel_Array:totalSize += modelSpecifier_.indices_.size();break;
			case DataModel_Dictionary:totalSize += modelSpecifier_.keys_.size();break;
			default:totalSize += length_;break;
			}
		}
		else
			totalSize += length_;
		return totalSize;
	}

	retT StoredDataSpecifier::attachRootElement( boost::weak_ptr<PacketElement> _pRootElement )
	{
		R(PacketElement::attachRootElement(_pRootElement));
		R(modelSpecifier_.indices_.attachRootElement(_pRootElement));
		R(modelSpecifier_.keys_.attachRootElement(_pRootElement));
		RETSUCCESS;
	}

	/////////////////////////////////////////////////////////////////////////////////////

	FetchKindResponse::FetchKindResponse()
	{

	}

	FetchKindResponse::~FetchKindResponse()
	{

	}
}
